/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package com.plian.system.service.pf.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.plian.Tools.*;
import com.plian.Tools.pagedata.PageData;
import com.plian.system.common.status.CustomCode;
import com.plian.system.constant.baseinfo.ValueSetConstant;
import com.plian.system.constant.sys.FormStatusConstant;
import com.plian.system.constant.sys.FormTypeConstant;
import com.plian.system.entity.pf.BaseChildGrantSalary;
import com.plian.system.entity.pf.ChildGrantSalary;
import com.plian.system.mapper.pf.BaseChildGrantSalaryMapper;
import com.plian.system.model.CommonCode;
import com.plian.system.model.ObjResult;
import com.plian.system.model.R;
import com.plian.system.mybatis.base.BaseFlowService;
import com.plian.system.mybatis.base.BaseServiceImpl;
import com.plian.system.service.bt.baseinfo.BaseInfoService;
import com.plian.system.service.pf.IBaseChildGrantSalaryService;
import com.plian.system.service.pf.IChildGrantSalaryService;
import com.plian.system.service.sys.code.IFormCodeService;
import com.plian.system.service.sys.orgzation.OrgzationService;
import com.plian.system.service.wf.FormWorkflowService;
import com.plian.system.vo.pf.BaseChildGrantSalaryVO;
import com.plian.system.vo.pf.SalaryMonthStatisticsVO;
import com.plian.system.wrapper.pf.BaseChildGrantSalaryWrapper;
import com.plian.system.wrapper.pf.ChildGrantSalaryWrapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static com.plian.system.constant.sys.FormStatusConstant.UNREVIEWED;

/**
 * 职工工资发放主表_子企业 服务实现类
 *
 * @author
 * @since 2019-09-27
 */
@Slf4j
@Service
@AllArgsConstructor
public class BaseChildGrantSalaryServiceImpl extends BaseServiceImpl<BaseChildGrantSalaryMapper, BaseChildGrantSalary> implements IBaseChildGrantSalaryService, BaseFlowService {

	private FormWorkflowService formWorkflowService;

	private IFormCodeService formCodeService;

	private IChildGrantSalaryService childGrantSalaryService;

	private BaseInfoService baseInfoService;

	private OrgzationService orgzationService;

	private BaseChildGrantSalaryWrapper baseChildGrantSalaryWrapper;

	private ChildGrantSalaryWrapper childGrantSalaryWrapper;

//	private static Map<String, String> countCategoryMap = new HashMap<>();
//	// k1 tokenOrgId k:code v:name
//	private static Map<String, Map<String, String>> tokenOrgMap = new HashMap<>();

	@Override
	public boolean saveOrUpdate(BaseChildGrantSalary baseChildGrantSalary) {

		if (!Optional.ofNullable(baseChildGrantSalary.getStatus()).isPresent()) {
			baseChildGrantSalary.setStatus(FormStatusConstant.UNREVIEWED);
		}
		if (!Optional.ofNullable(baseChildGrantSalary.getId()).isPresent()) {
			baseChildGrantSalary.setCode(formCodeService.getCode(FormTypeConstant.PF_BASE_CHILD_GRANT_SALARY));
			baseChildGrantSalary.setFormType(String.valueOf(FormTypeConstant.PF_BASE_CHILD_GRANT_SALARY));
		}

		return super.saveOrUpdate(baseChildGrantSalary);
	}

	@Override
	@Transactional(rollbackFor=RuntimeException.class)
	public boolean deleteLogic(List<Long> ids) {
		for (Long id : ids) {
			BaseChildGrantSalary baseChildGrantSalary = getById(id);
			if (baseChildGrantSalary == null) {
				return false;
			} else if (baseChildGrantSalary.getStatus() != null &&
					(baseChildGrantSalary.getStatus() != FormStatusConstant.STASH && baseChildGrantSalary.getStatus() != FormStatusConstant.UNREVIEWED)) {
				return false;
			}
			formWorkflowService.deleteProcessInstance(String.valueOf(id));
		}

		boolean result = super.deleteLogic(ids);
		if (result){
			childGrantSalaryService.deleteByParentId(ids);
		}

		return result;
	}

	@Override
	public HashMap<String,Object> commit(String id) {
		handleStatus(Long.valueOf(id), FormStatusConstant.FLOW);

		//将需要提交的流程变量返回，用于工作流侧
		return new HashMap<String,Object>();
	}

	@Override
	public Boolean finish(String id) {
		return handleStatus(Long.valueOf(id), FormStatusConstant.FINISH);
	}

	@Override
	public Boolean reject(String id, int formState, String comment) {
		return handleStatus(Long.valueOf(id), formState);
	}


	@Override
	public String checkMonth(BaseChildGrantSalary baseChildGrantSalary) {
		if (!Optional.ofNullable(baseChildGrantSalary.getFillingMonth()).isPresent()) {
			return "填报时间为空";
		}
		if (!Optional.ofNullable(baseChildGrantSalary.getFillingUnitId()).isPresent()){
			return "填报单位为空";
		}
		LambdaQueryWrapper<BaseChildGrantSalary> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(BaseChildGrantSalary::getFillingUnitId,baseChildGrantSalary.getFillingUnitId());
		queryWrapper.eq(BaseChildGrantSalary::getFillingMonth, baseChildGrantSalary.getFillingMonth());
		BaseChildGrantSalary one = getOne(queryWrapper);
		if (!Optional.ofNullable(one).isPresent()){
			return null;
		}
		if (one.getId().equals(baseChildGrantSalary.getId())){
			return null;
		}
		return "该月份已填报";
	}


	/**
	 * 统一处理状态机事件方法
	 *
	 * @param id          主键
	 * @param updateStatus  更新状态
	 * @return boolean
	 */
	private Boolean handleStatus(Long id, int updateStatus) {
		try {
			BaseChildGrantSalary baseChildGrantSalary = getById(id);
			/**
			 * 设置审批人和审批时间
			 */
			if (updateStatus == FormStatusConstant.FINISH){
				baseChildGrantSalary.setApprovedUser(TokenUtil.getTokenUserId());
				Date now = DateUtil.now();
				baseChildGrantSalary.setApprovedTime(now);
			}
			baseChildGrantSalary.setStatus(updateStatus);
			updateById(baseChildGrantSalary);
			return true;
		} catch (Exception e) {
			log.error(ExceptionUtils.getFullStackTrace(e));
			return false;
		}
	}


	@Override
	public List<PageData> findByIds(List<String> formIds) {
		LambdaQueryWrapper<BaseChildGrantSalary> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.in(BaseChildGrantSalary::getId, Func.toLongList(StringUtils.join(formIds, StringPool.COMMA)));
		List<BaseChildGrantSalary> baseChildGrantSalary = list(queryWrapper);
		List<BaseChildGrantSalaryVO> baseChildGrantSalaryVOS= baseChildGrantSalaryWrapper.entityToVO(baseChildGrantSalary);
		List<PageData> pageDataList = new ArrayList<>();
		try{
			if (CollectionUtil.isNotEmpty(baseChildGrantSalaryVOS)){
				for (BaseChildGrantSalaryVO vo : baseChildGrantSalaryVOS){
					PageData pd = new PageData();
					pd.put("id", vo.getId());
					pd.put("UNITNAME", vo.getFillingUnitName());
					pd.put("APPLICANTNAME", vo.getCreateUserName());
					pd.put("applicantId", vo.getCreateUser());
					pd.put("applyOrganizationId", vo.getFillingUnitId());
					pd.put("formType", FormTypeConstant.PF_BASE_CHILD_GRANT_SALARY);
					pd.put("orgName", vo.getFillingUnitName());
					pageDataList.add(pd);
				}
			}

			return pageDataList;
		} catch (Exception e) {
			log.error(ExceptionUtils.getFullStackTrace(e));
		}
		return pageDataList;
	}

	@Override
	public List<Integer> getFormType() {
		return Arrays.asList(FormTypeConstant.PF_BASE_CHILD_GRANT_SALARY);
	}

	@Override
	@Transactional(rollbackFor=RuntimeException.class)
	public boolean submit(BaseChildGrantSalary baseChildGrantSalary) {
		boolean result = saveOrUpdate(baseChildGrantSalary);
		if (result){

			List<ChildGrantSalary> childGrantSalaries = baseChildGrantSalary.getChildGrantSalaries();
			if (CollectionUtil.isNotEmpty(childGrantSalaries)){
				for (ChildGrantSalary childGrantSalary : childGrantSalaries){
					if (childGrantSalary.getId() != null &&
							Optional.ofNullable(childGrantSalary.getIsDeleted()).isPresent() && childGrantSalary.getIsDeleted().intValue() == 1) {
						childGrantSalaryService.removeById(childGrantSalary.getId());
					}else {
						childGrantSalary.setBaseChildGrantSalaryId(baseChildGrantSalary.getId());
						childGrantSalaryService.saveOrUpdate(childGrantSalary);
					}
				}
			}
		}
		return result;
	}

	@Override
	public R<BaseChildGrantSalaryVO> getDetailObj(BaseChildGrantSalaryVO baseChildGrantSalaryVO) {
		if(!Optional.ofNullable(baseChildGrantSalaryVO).isPresent()){
			return new R(CommonCode.FAIL);
		}
		List<ChildGrantSalary> childGrantSalaries = childGrantSalaryService
				.list(new LambdaQueryWrapper<ChildGrantSalary>().eq(ChildGrantSalary::getBaseChildGrantSalaryId, baseChildGrantSalaryVO.getId()));
		baseChildGrantSalaryVO.setChildGrantSalaryVOS(childGrantSalaryWrapper.entityToVO(childGrantSalaries));
		return R.data(baseChildGrantSalaryVO);
	}

	@Override
	public void goBackToStash(String formId) {
		handleStatus(Long.valueOf(formId), UNREVIEWED);
	}

	@Override
	public List<SalaryMonthStatisticsVO> yearStatistics(String fillingYear, List<String> fillingUnitIds) {
		List<SalaryMonthStatisticsVO> allResults = new ArrayList<>();
		Map<String, String> countCategoryMap = baseInfoService.getChildMap(ValueSetConstant.CHILD_SALARY_COUNT_CATEGORY);
		List<SalaryMonthStatisticsVO> allChildResults = getList(countCategoryMap, fillingYear, fillingUnitIds);
		List<SalaryMonthStatisticsVO> endResults = initEndSummary(countCategoryMap);

		if(CollectionUtil.isNotEmpty(allChildResults)){
			allResults.addAll(endResults);
			// 所有子公司 合计
			allResults.addAll(allChildResults);
			Map<String, List<SalaryMonthStatisticsVO>> baseMap = allChildResults.stream().collect(Collectors.groupingBy(SalaryMonthStatisticsVO::getCountCategoryId));
			for (SalaryMonthStatisticsVO end : endResults){
				List<SalaryMonthStatisticsVO> childVOS = baseMap.get(end.getCountCategoryId());
				for (SalaryMonthStatisticsVO childVO : childVOS){
					end.setMonthAverage(BigDecimalUtil.add(end.getMonthAverage() , childVO.getMonthAverage()));
					// 12个月在岗人数
					end.setJanuaryOnJobNumber(BigDecimalUtil.add(end.getJanuaryOnJobNumber() , childVO.getJanuaryOnJobNumber()));
					end.setFebruaryOnJobNumber(BigDecimalUtil.add(end.getFebruaryOnJobNumber() , childVO.getFebruaryOnJobNumber()));
					end.setMarchOnJobNumber(BigDecimalUtil.add(end.getMarchOnJobNumber() , childVO.getMarchOnJobNumber()));
					end.setAprilOnJobNumber(BigDecimalUtil.add(end.getAprilOnJobNumber() , childVO.getAprilOnJobNumber()));
					end.setMayOnJobNumber(BigDecimalUtil.add(end.getMayOnJobNumber() , childVO.getMayOnJobNumber()));
					end.setJuneOnJobNumber(BigDecimalUtil.add(end.getJuneOnJobNumber() , childVO.getJuneOnJobNumber()));
					end.setJulyOnJobNumber(BigDecimalUtil.add(end.getJuneOnJobNumber() , childVO.getJulyOnJobNumber()));
					end.setAugustOnJobNumber(BigDecimalUtil.add(end.getAugustOnJobNumber() , childVO.getAugustOnJobNumber()));
					end.setSeptemberOnJobNumber(BigDecimalUtil.add(end.getSeptemberOnJobNumber() , childVO.getSeptemberOnJobNumber()));
					end.setOctoberOnJobNumber(BigDecimalUtil.add(end.getOctoberOnJobNumber() , childVO.getOctoberOnJobNumber()));
					end.setNovemberOnJobNumber(BigDecimalUtil.add(end.getNovemberOnJobNumber() , childVO.getNovemberOnJobNumber()));
					end.setDecemberOnJobNumber(BigDecimalUtil.add(end.getDecemberOnJobNumber() , childVO.getDecemberOnJobNumber()));
					end.setYearAverage(BigDecimalUtil.add(end.getYearAverage(), childVO.getYearAverage()));


					end.setTotalActualGrantAmount(BigDecimalUtil.add(end.getTotalActualGrantAmount() , (childVO.getTotalActualGrantAmount())));
					end.setTotalActualProvision(BigDecimalUtil.add(end.getTotalActualProvision() , (childVO.getTotalActualProvision())));
					// 12个月实际发放
					end.setJanuaryActualGrantAmount(BigDecimalUtil.add(end.getJanuaryActualGrantAmount() , (childVO.getJanuaryActualGrantAmount())));
					end.setFebruaryActualGrantAmount(BigDecimalUtil.add(end.getFebruaryActualGrantAmount() , (childVO.getFebruaryActualGrantAmount())));
					end.setMarchActualGrantAmount(BigDecimalUtil.add(end.getMarchActualGrantAmount() , (childVO.getMarchActualGrantAmount())));
					end.setAprilActualGrantAmount(BigDecimalUtil.add(end.getAprilActualGrantAmount() , (childVO.getAprilActualGrantAmount())));
					end.setMayActualGrantAmount(BigDecimalUtil.add(end.getMayActualGrantAmount() , (childVO.getMayActualGrantAmount())));
					end.setJuneActualGrantAmount(BigDecimalUtil.add(end.getJuneActualGrantAmount() , (childVO.getJuneActualGrantAmount())));
					end.setJulyActualGrantAmount(BigDecimalUtil.add(end.getJuneActualGrantAmount() , (childVO.getJulyActualGrantAmount())));
					end.setAugustActualGrantAmount(BigDecimalUtil.add(end.getAugustActualGrantAmount() , (childVO.getAugustActualGrantAmount())));
					end.setSeptemberActualGrantAmount(BigDecimalUtil.add(end.getSeptemberActualGrantAmount() , (childVO.getSeptemberActualGrantAmount())));
					end.setOctoberActualGrantAmount(BigDecimalUtil.add(end.getOctoberActualGrantAmount() , (childVO.getOctoberActualGrantAmount())));
					end.setNovemberActualGrantAmount(BigDecimalUtil.add(end.getNovemberActualGrantAmount() , (childVO.getNovemberActualGrantAmount())));
					end.setDecemberActualGrantAmount(BigDecimalUtil.add(end.getDecemberActualGrantAmount() , (childVO.getDecemberActualGrantAmount())));

//					end.setGrantProgress(BigDecimalUtil.add(end.getGrantProgress() , (childVO.getGrantProgress())));
					end.setAverageSalary(BigDecimalUtil.add(end.getAverageSalary() , (childVO.getAverageSalary())));
					end.setLastAverageSalary(BigDecimalUtil.add(end.getLastAverageSalary() , (childVO.getLastAverageSalary())));
					end.setActualPeopleNumber(BigDecimalUtil.add(end.getActualPeopleNumber() , childVO.getActualPeopleNumber()));
//					end.setWageIncreases(BigDecimalUtil.add(end.getWageIncreases() , (childVO.getWageIncreases())));

				}
				end.setGrantProgress(BigDecimalUtil.divide(end.getTotalActualGrantAmount(), end.getBudget(), 4, BigDecimal.ROUND_HALF_UP, 100));
				if (Optional.ofNullable(end.getAverageSalary()).isPresent() && Optional.ofNullable(end.getLastAverageSalary()).isPresent()) {
					end.setWageIncreases(end.getAverageSalary().subtract(end.getLastAverageSalary())
							.multiply(new BigDecimal(100)).divide(end.getLastAverageSalary(), 4, BigDecimal.ROUND_HALF_UP));
				}
			}
		}

		return allResults;
	}


	@Override
	@Transactional(rollbackFor=RuntimeException.class)
	public ObjResult addTree(BaseChildGrantSalary baseChildGrantSalary) {
		String fillingMonth = baseChildGrantSalary.getFillingMonth();
		if (StringUtil.isBlank(fillingMonth)){
			return new ObjResult(CustomCode.builder().message("填报年月为空").code(1999).success(false).build());
		}
		String fillingUnitId = TokenUtil.getTokenOrgId();
		//子企业工资填报
		BaseChildGrantSalary oneOldBase = getOne(new LambdaQueryWrapper<BaseChildGrantSalary>()
				.eq(BaseChildGrantSalary::getFillingMonth, fillingMonth)
				.eq(BaseChildGrantSalary::getFillingUnitId, fillingUnitId));
		if (Optional.ofNullable(oneOldBase).isPresent()){
			return new ObjResult(CustomCode.builder().message("该年月已填报").code(1999).success(false).build());
		}

		BaseChildGrantSalary oneBase = BaseChildGrantSalary.builder().fillingMonth(fillingMonth).fillingUnitId(fillingUnitId).build();
		boolean result = saveOrUpdate(oneBase);
		HashMap<String, Object> processVariable = new HashMap<>();
		formWorkflowService.startProcessAndSimulate(String.valueOf(oneBase.getId()),oneBase.getFormType(),processVariable);

		//上月填报数据
		List<ChildGrantSalary> oldList = getLastList(fillingMonth, fillingUnitId);
		//获取本年已填报数据
		String fillingYear = fillingMonth.split(StringPool.DASH)[0];
		List<ChildGrantSalary> grantSalaries = getFillingList(fillingYear, fillingUnitId);
		String lastFillingYear = String.valueOf(Integer.valueOf(fillingYear) - 1);

		// 历史数据填充
		List<ChildGrantSalary> childGrantSalaries = lastInit(oldList, lastFillingYear, fillingUnitId, oneBase.getId(), grantSalaries);

		if (CollectionUtil.isNotEmpty(childGrantSalaries)){
			childGrantSalaryService.saveBatch(childGrantSalaries);
		}

		return result ? new ObjResult(CommonCode.SUCCESS) : new ObjResult(CommonCode.FAIL);
	}

	@Override
	public ObjResult isHavePre() {
		PageData org = orgzationService.getCompanyNameById(TokenUtil.getTokenOrgId());
		PageData pd = new PageData();
		ObjResult objResult = new ObjResult(CommonCode.SUCCESS);
		boolean isHave = false;
		if (Optional.ofNullable(org).isPresent()){
			String orgCode = (String)org.get("orgCode");
			if (StringUtil.isNotBlank(orgCode) && orgCode.length() == 10){
				isHave = true;
			}
		}else {
			return new ObjResult(CustomCode.builder().message("登录信息获取失败").code(1999).success(false).build());
		}
		pd.put("isHave", isHave);
		objResult.setPageData(pd);
		return objResult;
	}

	/**
	 * 单家企业年统计
	 * @param fillingYear
	 * @param fillingUnitId
	 * @return
	 */
	private List<SalaryMonthStatisticsVO> getOneCompanyList(Map<String, String> countCategoryMap, String fillingYear, String fillingUnitId) {

		List<BaseChildGrantSalary> baseChildList = list(new LambdaQueryWrapper<BaseChildGrantSalary>()
				.eq(BaseChildGrantSalary::getStatus, FormStatusConstant.FINISH)
				.eq(BaseChildGrantSalary::getFillingUnitId, fillingUnitId)
				.like(BaseChildGrantSalary::getFillingMonth, fillingYear));
		List<SalaryMonthStatisticsVO> allResults = new ArrayList<>();

		Map<Long, List<BaseChildGrantSalary>> baseMap = new HashMap<>();
		Map<String, List<ChildGrantSalary>> map = new HashMap<>();

		if (CollectionUtil.isNotEmpty(baseChildList)){
			baseMap = baseChildList.stream().collect(Collectors.groupingBy(BaseChildGrantSalary::getId));
			List<ChildGrantSalary> grantSalaries = childGrantSalaryService.list(new LambdaQueryWrapper<ChildGrantSalary>()
					.in(ChildGrantSalary::getBaseChildGrantSalaryId, baseChildList.stream().map(BaseChildGrantSalary::getId).collect(Collectors.toList())));
			// 按子企业id分类
			map = grantSalaries.stream().collect(Collectors.groupingBy(ChildGrantSalary::getChildCompanyId));
		}

		//子企业赋值

		String k = fillingUnitId;
		String v = "";

		Map<String, List<ChildGrantSalary>> childMap = new HashMap<>();
		if (map.containsKey(k)){
			List<ChildGrantSalary> childGrantSalaries = map.get(k);
			// 按统计类型分类
			childMap = childGrantSalaries.stream().collect(Collectors.groupingBy(ChildGrantSalary::getChildCountCategoryId));
		}

		List<SalaryMonthStatisticsVO> results = initSummary(countCategoryMap, k, v);
		for (SalaryMonthStatisticsVO result : results){
			if (childMap.containsKey(result.getCountCategoryId())){
				BigDecimal onJobNumber = new BigDecimal(0);
				BigDecimal total = new BigDecimal(0);
				BigDecimal totalProvision = new BigDecimal(0);
				for (ChildGrantSalary grantSalary : childMap.get(result.getCountCategoryId())){
					setValue(grantSalary, result, baseMap.get(grantSalary.getBaseChildGrantSalaryId()).get(0).getFillingMonth());
					onJobNumber = BigDecimalUtil.add(onJobNumber, grantSalary.getOnJobNumber());
					if (Optional.ofNullable(grantSalary.getActualGrantAmount()).isPresent()){
						total = total.add(grantSalary.getActualGrantAmount());
					}
					if (Optional.ofNullable(grantSalary.getActualProvisionThisMonth()).isPresent()){
						totalProvision = totalProvision.add(grantSalary.getActualProvisionThisMonth());
					}
				}

				int size = childMap.get(result.getCountCategoryId()).size();
				ChildGrantSalary grantSalary = childMap.get(result.getCountCategoryId()).get(size - 1);

				result.setMonthAverage(BigDecimalUtil.divide(onJobNumber, new BigDecimal(size), 4, BigDecimal.ROUND_HALF_UP));
				result.setYearAverage(result.getMonthAverage());
				result.setTotalActualGrantAmount(total);
				result.setTotalActualProvision(totalProvision);
				result.setBudget(grantSalary.getBudget());
				result.setGrantProgress(BigDecimalUtil.divide(total, grantSalary.getBudget(), 4, BigDecimal.ROUND_HALF_UP, 100));

				result.setAverageSalary(BigDecimalUtil.divide(total, result.getYearAverage(), 4, BigDecimal.ROUND_HALF_UP));
				result.setLastAverageSalary(grantSalary.getAverageSalary());
				result.setActualPeopleNumber(grantSalary.getActualPeopleNumber());
				if (Optional.ofNullable(result.getAverageSalary()).isPresent() && Optional.ofNullable(result.getLastAverageSalary()).isPresent()) {
					result.setWageIncreases(result.getAverageSalary().subtract(result.getLastAverageSalary())
							.multiply(new BigDecimal(100)).divide(result.getLastAverageSalary(), 4, BigDecimal.ROUND_HALF_UP));
				}
			}
		}
		allResults.addAll(results);

		return allResults;
	}

	/**
	 * 所有子企业，统计
	 * @param fillingYear
	 * @param fillingUnitIds
	 * @return
	 */
	private List<SalaryMonthStatisticsVO> getList(Map<String, String> countCategoryMap, String fillingYear, List<String> fillingUnitIds) {
		List<PageData> childList = orgzationService.getChildrenByPId(fillingUnitIds.get(0));
		if (CollectionUtil.isEmpty(childList)){
			return new ArrayList<>();
		}
		List<String> childIds = new ArrayList<>();
		Map<String, String> childOrgMap = new HashMap<>();
		for (PageData child : childList){
			childIds.add((String)child.get("id"));
			childOrgMap.put((String)child.get("id"), (String)child.get("name"));
		}

		List<BaseChildGrantSalary> baseChildList = list(new LambdaQueryWrapper<BaseChildGrantSalary>()
				.eq(BaseChildGrantSalary::getStatus, FormStatusConstant.FINISH)
				.in(BaseChildGrantSalary::getFillingUnitId, childIds)
				.like(BaseChildGrantSalary::getFillingMonth, fillingYear));
		List<SalaryMonthStatisticsVO> allResults = new ArrayList<>();

		if (CollectionUtil.isNotEmpty(childOrgMap)){
			Map<Long, List<BaseChildGrantSalary>> baseMap = new HashMap<>();
			Map<String, List<ChildGrantSalary>> map = new HashMap<>();

			if (CollectionUtil.isNotEmpty(baseChildList)){
				baseMap = baseChildList.stream().collect(Collectors.groupingBy(BaseChildGrantSalary::getId));
				List<ChildGrantSalary> grantSalaries = childGrantSalaryService.list(new LambdaQueryWrapper<ChildGrantSalary>()
						.in(ChildGrantSalary::getBaseChildGrantSalaryId, baseChildList.stream().map(BaseChildGrantSalary::getId).collect(Collectors.toList())));
				// 按子企业id分类
				map = grantSalaries.stream().collect(Collectors.groupingBy(ChildGrantSalary::getChildCompanyId));
			}

			//子企业赋值
			Iterator<Map.Entry<String, String>> it = childOrgMap.entrySet().iterator();

//			Map<String, String> orgMap = tokenOrgMap.get(TokenUtil.getTokenOrgId());
			while (it.hasNext()) {
				Map.Entry<String, String> entry = it.next();
				String k = entry.getKey();
				String v = entry.getValue();

				Map<String, List<ChildGrantSalary>> childMap = new HashMap<>();
				if (map.containsKey(k)){
					List<ChildGrantSalary> childGrantSalaries = map.get(k);
					// 按统计类型分类
					childMap = childGrantSalaries.stream().collect(Collectors.groupingBy(ChildGrantSalary::getChildCountCategoryId));
				}

				List<SalaryMonthStatisticsVO> results = initSummary(countCategoryMap, k, v);
				for (SalaryMonthStatisticsVO result : results){
					if (childMap.containsKey(result.getCountCategoryId())){
						BigDecimal onJobNumber = new BigDecimal(0);
						BigDecimal total = new BigDecimal(0);
						BigDecimal totalProvision = new BigDecimal(0);
						for (ChildGrantSalary grantSalary : childMap.get(result.getCountCategoryId())){
							setValue(grantSalary, result, baseMap.get(grantSalary.getBaseChildGrantSalaryId()).get(0).getFillingMonth());
							onJobNumber = BigDecimalUtil.add(onJobNumber, grantSalary.getOnJobNumber());
							if (Optional.ofNullable(grantSalary.getActualGrantAmount()).isPresent()){
								total = total.add(grantSalary.getActualGrantAmount());
							}
							if (Optional.ofNullable(grantSalary.getActualProvisionThisMonth()).isPresent()){
								totalProvision = totalProvision.add(grantSalary.getActualProvisionThisMonth());
							}
						}

						int size = childMap.get(result.getCountCategoryId()).size();
						ChildGrantSalary grantSalary = childMap.get(result.getCountCategoryId()).get(size - 1);

						result.setMonthAverage(BigDecimalUtil.divide(onJobNumber, new BigDecimal(size), 4, BigDecimal.ROUND_HALF_UP));
						result.setYearAverage(result.getMonthAverage());
						result.setTotalActualGrantAmount(total);
						result.setTotalActualProvision(totalProvision);
						result.setBudget(grantSalary.getBudget());
						result.setGrantProgress(BigDecimalUtil.divide(total, grantSalary.getBudget(), 4, BigDecimal.ROUND_HALF_UP, 100));

						result.setAverageSalary(BigDecimalUtil.divide(total, result.getYearAverage(), 4, BigDecimal.ROUND_HALF_UP));
						result.setLastAverageSalary(grantSalary.getAverageSalary());
						result.setActualPeopleNumber(grantSalary.getActualPeopleNumber());
						if (Optional.ofNullable(result.getAverageSalary()).isPresent() && Optional.ofNullable(result.getLastAverageSalary()).isPresent()) {
							result.setWageIncreases(result.getAverageSalary().subtract(result.getLastAverageSalary())
									.multiply(new BigDecimal(100)).divide(result.getLastAverageSalary(), 4, BigDecimal.ROUND_HALF_UP));
						}
					}
				}
				allResults.addAll(results);
			}
		}
		return allResults;
	}


	/**
	 * 按月赋值
	 * @param grantSalary
	 * @param result
	 * @param fillingMonth
	 */
	private void setValue(ChildGrantSalary grantSalary, SalaryMonthStatisticsVO result, String fillingMonth){
		int month = Integer.valueOf(fillingMonth.split("-")[1]);
		switch (month){
			case 1:
				result.setJanuaryOnJobNumber(grantSalary.getOnJobNumber());
				result.setJanuaryActualGrantAmount(grantSalary.getActualGrantAmount());
				break;
			case 2:
				result.setFebruaryOnJobNumber(grantSalary.getOnJobNumber());
				result.setFebruaryActualGrantAmount(grantSalary.getActualGrantAmount());
				break;
			case 3:
				result.setMarchOnJobNumber(grantSalary.getOnJobNumber());
				result.setMarchActualGrantAmount(grantSalary.getActualGrantAmount());
				break;
			case 4:
				result.setAprilOnJobNumber(grantSalary.getOnJobNumber());
				result.setAprilActualGrantAmount(grantSalary.getActualGrantAmount());
				break;
			case 5:
				result.setMayOnJobNumber(grantSalary.getOnJobNumber());
				result.setMayActualGrantAmount(grantSalary.getActualGrantAmount());
				break;
			case 6:
				result.setJuneOnJobNumber(grantSalary.getOnJobNumber());
				result.setJuneActualGrantAmount(grantSalary.getActualGrantAmount());
				break;
			case 7:
				result.setJulyOnJobNumber(grantSalary.getOnJobNumber());
				result.setJulyActualGrantAmount(grantSalary.getActualGrantAmount());
				break;
			case 8:
				result.setAugustOnJobNumber(grantSalary.getOnJobNumber());
				result.setAugustActualGrantAmount(grantSalary.getActualGrantAmount());
				break;
			case 9:
				result.setSeptemberOnJobNumber(grantSalary.getOnJobNumber());
				result.setSeptemberActualGrantAmount(grantSalary.getActualGrantAmount());
				break;
			case 10:
				result.setOctoberOnJobNumber(grantSalary.getOnJobNumber());
				result.setOctoberActualGrantAmount(grantSalary.getActualGrantAmount());
				break;
			case 11:
				result.setNovemberOnJobNumber(grantSalary.getOnJobNumber());
				result.setNovemberActualGrantAmount(grantSalary.getActualGrantAmount());
				break;
			case 12:
				result.setDecemberOnJobNumber(grantSalary.getOnJobNumber());
				result.setDecemberActualGrantAmount(grantSalary.getActualGrantAmount());
				break;
			default:
				break;

		}
	}

	private List<SalaryMonthStatisticsVO> initSummary(Map<String, String> countCategoryMap, String childCompanyId, String childCompanyName){
		List<SalaryMonthStatisticsVO> initList = new ArrayList<>();
        countCategoryMap.forEach((k,v) ->{
        	if ("合计".equals(v)){
				SalaryMonthStatisticsVO init = SalaryMonthStatisticsVO.builder().countCategoryId(k).countCategoryName(childCompanyName).childCompanyId(childCompanyId).build();
				initList.add(init);
			}else {
				SalaryMonthStatisticsVO init = SalaryMonthStatisticsVO.builder().countCategoryId(k).countCategoryName(v).childCompanyId(childCompanyId).build();
				initList.add(init);
			}
		});
		Collections.sort(initList, (a, b) -> Integer.valueOf(a.getCountCategoryId()).compareTo(Integer.valueOf(b.getCountCategoryId())));
		return initList;
	}


	private List<SalaryMonthStatisticsVO> initEndSummary(Map<String, String> countCategoryMap){
		List<SalaryMonthStatisticsVO> initList = new ArrayList<>();
		countCategoryMap.forEach((k,v) ->{
				SalaryMonthStatisticsVO init = SalaryMonthStatisticsVO.builder().countCategoryId(k).countCategoryName(v).build();
				initList.add(init);
			}
		);
		Collections.sort(initList, (a, b) -> Integer.valueOf(a.getCountCategoryId()).compareTo(Integer.valueOf(b.getCountCategoryId())));
		for (int i = 0; i < 3; i++){
			SalaryMonthStatisticsVO init = initList.get(i);
			switch (i){
				case 0:
					init.setCountCategoryName("子企业工资总额");
					break;
				case 1:
					init.setCountCategoryName("① 子企业负责人小计");
					break;
				case 2:
					init.setCountCategoryName("② 子企业职业经理人小计");
					break;
			}
		}
		return initList;
	}

	/**
	 *
	 * @param initList 该子企业初始化数组
	 * @param salaryMonthStatisticsVOS 统计数据
	 */
	private void lastInit(List<ChildGrantSalary> initList, List<SalaryMonthStatisticsVO> salaryMonthStatisticsVOS){
		if (CollectionUtil.isNotEmpty(salaryMonthStatisticsVOS)){
			for (int i = 0; i<salaryMonthStatisticsVOS.size(); i++){
				initList.get(i).setAverageSalary(salaryMonthStatisticsVOS.get(i).getAverageSalary());
				initList.get(i).setActualPeopleNumber(salaryMonthStatisticsVOS.get(i).getYearAverage());
                initList.get(i).setLastYearSalary(salaryMonthStatisticsVOS.get(i).getTotalActualGrantAmount());
			}
		}
	}

	/**
	 * 获取上月数据
	 * @param fillingMonth
	 * @return
	 */
	private List<ChildGrantSalary> getLastList(String fillingMonth, String fillingUnitId){
		Calendar c = Calendar.getInstance();
		Date lastDate = DateUtil.parse(fillingMonth, DateUtil.PATTERN_MONTH);
		c.setTime(lastDate);
		c.add(Calendar.MONTH, -1);
		String lastMonth = DateUtil.format(c.getTime(), DateUtil.PATTERN_MONTH);

		BaseChildGrantSalary last = null;
		if (DateUtil.isTheSameYear(lastDate, c.getTime())) {
			last = getOne(new LambdaQueryWrapper<BaseChildGrantSalary>()
					.eq(BaseChildGrantSalary::getFillingUnitId, fillingUnitId)
					.eq(BaseChildGrantSalary::getFillingMonth, lastMonth));
		}

		//上月填报数据
		List<ChildGrantSalary> oldList = new ArrayList<>();
		if (Optional.ofNullable(last).isPresent()){
			oldList = childGrantSalaryService.list(new LambdaQueryWrapper<ChildGrantSalary>().eq(ChildGrantSalary::getBaseChildGrantSalaryId, last.getId()));
		}
		return oldList;
	}

	/**
	 * 获取本年度已填报数据
	 * @param fillingYear
	 * @return
	 */
	private List<ChildGrantSalary> getFillingList(String fillingYear, String fillingUnitId){
		List<BaseChildGrantSalary> baseList = list(new LambdaQueryWrapper<BaseChildGrantSalary>()
				.eq(BaseChildGrantSalary::getFillingUnitId, fillingUnitId)
				.like(BaseChildGrantSalary::getFillingMonth, fillingYear));
		List<ChildGrantSalary> grantSalaries = new ArrayList<>();
		if (CollectionUtil.isNotEmpty(baseList)) {
			grantSalaries = childGrantSalaryService.list(new LambdaQueryWrapper<ChildGrantSalary>()
					.eq(ChildGrantSalary::getBaseChildGrantSalaryId, baseList.get(0).getId()));
		}
		return grantSalaries;
	}

	/**
	 * 上月数据填充
	 * @param oldList 上月填报数据
	 * @param lastFillingYear 去年
	 * @param fillingUnitId 单位id
	 * @param fillingList 本年度已填报数据
	 * @return
	 */
	private List<ChildGrantSalary> lastInit(List<ChildGrantSalary> oldList, String lastFillingYear, String fillingUnitId, Long baseId, List<ChildGrantSalary> fillingList){
		Map<String, String> countCategoryMap = baseInfoService.getChildMap(ValueSetConstant.CHILD_SALARY_COUNT_CATEGORY);
		List<ChildGrantSalary> initList = new ArrayList<>();
		countCategoryMap.forEach((k,v) ->{
			ChildGrantSalary init = new ChildGrantSalary();
			init.setIsDeleted(0);
			init.setBaseChildGrantSalaryId(baseId);
			init.setCreateUser(fillingUnitId);
			init.setCreateTime(DateUtil.now());
			init.setCreateCompanyId(fillingUnitId);
			init.setChildCompanyId(fillingUnitId);
			init.setChildCountCategoryId(k);

			if (CollectionUtil.isNotEmpty(oldList)){
				//上月已填报情况
				for (ChildGrantSalary childGrantSalary : oldList){
					if (k.equals(childGrantSalary.getChildCountCategoryId())){
						init.setBudget(childGrantSalary.getBudget());
						init.setLastCumulativeGrantAmount(childGrantSalary.getCumulativeGrantAmount());
						init.setAverageSalary(childGrantSalary.getAverageSalary());
						init.setActualPeopleNumber(childGrantSalary.getActualPeopleNumber());
						init.setGrantProgress(childGrantSalary.getGrantProgress());
                        init.setLastYearSalary(childGrantSalary.getLastYearSalary());
						break;
					}
				}
			}else if(CollectionUtil.isNotEmpty(fillingList)){
				//上月未填报，但本年有填报数据情况
				for (ChildGrantSalary childGrantSalary : fillingList) {
					if (k.equals(childGrantSalary.getChildCountCategoryId())) {
						init.setBudget(childGrantSalary.getBudget());
						init.setAverageSalary(childGrantSalary.getAverageSalary());
						init.setActualPeopleNumber(childGrantSalary.getActualPeopleNumber());
                        init.setLastYearSalary(childGrantSalary.getLastYearSalary());
						break;
					}
				}
			}
			initList.add(init);
		});
		Collections.sort(initList, (a, b) -> Integer.valueOf(a.getChildCountCategoryId()).compareTo(Integer.valueOf(b.getChildCountCategoryId())));
		if (CollectionUtil.isEmpty(oldList) && CollectionUtil.isEmpty(fillingList) ){
			//没有填报数据 填充去年统计数据
			lastInit(initList, getOneCompanyList(countCategoryMap, lastFillingYear, fillingUnitId));
		}
		return initList;
	}
}
